#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>
#include <sched.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>

#define BUFFER_SIZE 1024 * 1024  // 1MB buffer
#define DEFAULT_PORT 8888
#define MAX_CLIENTS 64
#define MAX_INTERFACES 8

// 全局变量
volatile int running = 1;
pthread_mutex_t stats_mutex = PTHREAD_MUTEX_INITIALIZER;
long total_bytes = 0;
int active_clients = 0;
time_t start_time;

// 网络接口信息结构
typedef struct {
    char interface_name[16];
    char mac_address[18];
    int interface_index;
    long rx_bytes;
    long tx_bytes;
    int is_bond_slave;
} interface_info_t;

// 客户端信息结构
typedef struct {
    int client_fd;
    struct sockaddr_in client_addr;
    int client_id;
    long client_bytes;
    time_t connect_time;
    int cpu_core;
    char source_interface[16];  // 连接的源接口
} client_info_t;

void signal_handler(int sig) {
    (void)sig;
    printf("\n正在关闭服务器...\n");
    running = 0;
}

void print_usage(const char *program_name) {
    printf("用法: %s [选项]\n", program_name);
    printf("选项:\n");
    printf("  -p <端口>    指定监听端口 (默认: %d)\n", DEFAULT_PORT);
    printf("  -i <接口>    指定绑定的网络接口 (如: bond0, eth0)\n");
    printf("  -m           启用多接口绑定模式\n");
    printf("  -h           显示此帮助信息\n");
    printf("\n注意: 此服务器专门优化bond mode=4的负载均衡\n");
}

// 获取网络接口信息
int get_interface_info(interface_info_t *interfaces, int max_interfaces) {
    struct ifaddrs *ifaddr, *ifa;
    int count = 0;
    
    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        return 0;
    }
    
    for (ifa = ifaddr; ifa != NULL && count < max_interfaces; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == NULL) continue;
        
        // 只处理IPv4地址
        if (ifa->ifa_addr->sa_family != AF_INET) continue;
        
        // 跳过回环接口
        if (strcmp(ifa->ifa_name, "lo") == 0) continue;
        
        strcpy(interfaces[count].interface_name, ifa->ifa_name);
        interfaces[count].interface_index = if_nametoindex(ifa->ifa_name);
        interfaces[count].is_bond_slave = 0;
        
        // 获取MAC地址
        int sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock >= 0) {
            struct ifreq ifr;
            strcpy(ifr.ifr_name, ifa->ifa_name);
            if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
                unsigned char *mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;
                snprintf(interfaces[count].mac_address, sizeof(interfaces[count].mac_address),
                        "%02x:%02x:%02x:%02x:%02x:%02x",
                        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
            }
            close(sock);
        }
        
        // 检查是否是bond从属接口
        char bond_path[256];
        snprintf(bond_path, sizeof(bond_path), "/proc/net/bonding/%s", ifa->ifa_name);
        FILE *fp = fopen(bond_path, "r");
        if (fp) {
            char line[256];
            while (fgets(line, sizeof(line), fp)) {
                if (strstr(line, "Slave Interface")) {
                    interfaces[count].is_bond_slave = 1;
                    break;
                }
            }
            fclose(fp);
        }
        
        count++;
    }
    
    freeifaddrs(ifaddr);
    return count;
}

// 显示bond mode=4诊断信息
void show_bond_mode4_diagnostics() {
    printf("=== bond mode=4 诊断信息 ===\n");
    
    // 检查bond接口
    if (access("/proc/net/bonding", F_OK) == 0) {
        printf("发现的bond接口:\n");
        
        // 扫描所有bond接口
        for (int i = 0; i < 10; i++) {
            char bond_name[32];
            snprintf(bond_name, sizeof(bond_name), "bond%d", i);
            
            char bond_path[256];
            snprintf(bond_path, sizeof(bond_path), "/proc/net/bonding/%s", bond_name);
            
            if (access(bond_path, R_OK) == 0) {
                printf("  %s:\n", bond_name);
                
                FILE *fp = fopen(bond_path, "r");
                if (fp) {
                    char line[256];
                    while (fgets(line, sizeof(line), fp)) {
                        // 显示关键信息
                        if (strstr(line, "Bonding Mode") || 
                            strstr(line, "MII Status") ||
                            strstr(line, "Slave Interface") ||
                            strstr(line, "Currently Active Slave") ||
                            strstr(line, "MII Polling Interval") ||
                            strstr(line, "Up Delay") ||
                            strstr(line, "Down Delay")) {
                            printf("    %s", line);
                        }
                    }
                    fclose(fp);
                }
            }
        }
    }
    
    // 显示网络接口信息
    interface_info_t interfaces[MAX_INTERFACES];
    int count = get_interface_info(interfaces, MAX_INTERFACES);
    
    printf("\n网络接口详情:\n");
    printf("%-12s %-18s %-8s %-12s\n", "接口", "MAC地址", "索引", "类型");
    printf("%-12s %-18s %-8s %-12s\n", "----", "--------", "----", "----");
    
    for (int i = 0; i < count; i++) {
        const char *type = interfaces[i].is_bond_slave ? "bond从属" : "独立接口";
        printf("%-12s %-18s %-8d %-12s\n", 
               interfaces[i].interface_name,
               interfaces[i].mac_address,
               interfaces[i].interface_index,
               type);
    }
    
    printf("\n=== bond mode=4 优化建议 ===\n");
    printf("1. 检查交换机LACP配置:\n");
    printf("   - 确保交换机端口配置为LACP模式\n");
    printf("   - 检查LACP协商状态\n");
    printf("   - 验证聚合组配置\n");
    
    printf("\n2. 优化bond配置:\n");
    printf("   - 使用 xmit_hash_policy=layer3+4\n");
    printf("   - 设置合适的 miimon 间隔\n");
    printf("   - 考虑使用 balance-rr 模式进行测试\n");
    
    printf("\n3. 应用层优化:\n");
    printf("   - 使用多IP绑定\n");
    printf("   - 增加并发连接数\n");
    printf("   - 使用不同的源端口\n");
    
    printf("============================\n\n");
}

// 绑定socket到特定接口
int bind_socket_to_interface(int sockfd, const char *interface_name) {
    if (!interface_name) return 0;
    
    // 获取接口索引
    int ifindex = if_nametoindex(interface_name);
    if (ifindex == 0) {
        printf("警告: 无法获取接口 %s 的索引\n", interface_name);
        return -1;
    }
    
    // 设置SO_BINDTODEVICE
    if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, interface_name, strlen(interface_name)) == -1) {
        printf("警告: 无法绑定到接口 %s\n", interface_name);
        return -1;
    }
    
    printf("成功绑定到接口: %s (索引: %d)\n", interface_name, ifindex);
    return 0;
}

// 设置线程CPU亲和性
void set_thread_cpu_affinity(int cpu_core) {
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(cpu_core, &cpuset);
    
    if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) != 0) {
        printf("警告: 无法设置线程CPU亲和性到核心%d\n", cpu_core);
    }
}

// 客户端处理线程
void* handle_client(void* arg) {
    client_info_t *client = (client_info_t*)arg;
    char buffer[BUFFER_SIZE];
    ssize_t bytes_received;
    time_t last_update_time = time(NULL);
    
    // 设置线程CPU亲和性
    if (client->cpu_core >= 0) {
        set_thread_cpu_affinity(client->cpu_core);
    }
    
    printf("客户端%d连接: %s:%d (CPU核心: %d, 接口: %s)\n", 
           client->client_id,
           inet_ntoa(client->client_addr.sin_addr), 
           ntohs(client->client_addr.sin_port),
           client->cpu_core,
           client->source_interface);
    
    // 更新活跃客户端计数
    pthread_mutex_lock(&stats_mutex);
    active_clients++;
    pthread_mutex_unlock(&stats_mutex);
    
    // 接收数据
    while (running) {
        bytes_received = recv(client->client_fd, buffer, BUFFER_SIZE, 0);
        if (bytes_received <= 0) {
            if (bytes_received == 0) {
                printf("客户端%d断开连接\n", client->client_id);
            } else {
                perror("接收数据失败");
            }
            break;
        }
        
        client->client_bytes += bytes_received;
        
        // 更新全局统计
        pthread_mutex_lock(&stats_mutex);
        total_bytes += bytes_received;
        pthread_mutex_unlock(&stats_mutex);
        
        // 每秒显示一次进度
        time_t current_time = time(NULL);
        if (current_time != last_update_time) {
            double duration = difftime(current_time, start_time);
            if (duration > 0) {
                pthread_mutex_lock(&stats_mutex);
                long current_total = total_bytes;
                int current_clients = active_clients;
                pthread_mutex_unlock(&stats_mutex);
                
                double bandwidth_mbps = (current_total * 8.0) / (duration * 1024 * 1024);
                printf("\r活跃客户端: %d, 总接收: %.2f MB, 聚合带宽: %.2f Mbps", 
                       current_clients, current_total / (1024.0 * 1024.0), bandwidth_mbps);
                fflush(stdout);
            }
            last_update_time = current_time;
        }
    }
    
    // 更新活跃客户端计数
    pthread_mutex_lock(&stats_mutex);
    active_clients--;
    pthread_mutex_unlock(&stats_mutex);
    
    printf("\n客户端%d统计: 接收 %.2f MB (接口: %s)\n", 
           client->client_id, client->client_bytes / (1024.0 * 1024.0),
           client->source_interface);
    
    close(client->client_fd);
    free(client);
    
    return NULL;
}

int main(int argc, char *argv[]) {
    int server_fd;
    struct sockaddr_in server_addr;
    int port = DEFAULT_PORT;
    char *bind_interface = NULL;
    int multi_interface_mode = 0;
    int opt;
    int client_id = 0;
    
    // 解析命令行参数
    while ((opt = getopt(argc, argv, "p:i:mh")) != -1) {
        switch (opt) {
            case 'p':
                port = atoi(optarg);
                if (port <= 0 || port > 65535) {
                    fprintf(stderr, "错误: 端口号必须在1-65535之间\n");
                    exit(EXIT_FAILURE);
                }
                break;
            case 'i':
                bind_interface = optarg;
                break;
            case 'm':
                multi_interface_mode = 1;
                break;
            case 'h':
                print_usage(argv[0]);
                exit(EXIT_SUCCESS);
            default:
                print_usage(argv[0]);
                exit(EXIT_FAILURE);
        }
    }
    
    // 设置信号处理
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    // 显示bond mode=4诊断信息
    show_bond_mode4_diagnostics();
    
    // 创建socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("创建socket失败");
        exit(EXIT_FAILURE);
    }
    
    // 设置socket选项
    int opt_val = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val)) == -1) {
        perror("设置SO_REUSEADDR失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT, &opt_val, sizeof(opt_val)) == -1) {
        perror("设置SO_REUSEPORT失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    // 绑定到特定接口
    if (bind_interface) {
        if (bind_socket_to_interface(server_fd, bind_interface) == -1) {
            printf("警告: 接口绑定失败，使用系统默认\n");
        }
    }
    
    // 配置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);
    
    // 绑定socket
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("绑定socket失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    // 开始监听
    if (listen(server_fd, MAX_CLIENTS) == -1) {
        perror("监听失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    printf("bond mode=4 优化服务器启动成功\n");
    printf("================================\n");
    printf("监听端口: %d\n", port);
    printf("最大并发连接: %d\n", MAX_CLIENTS);
    printf("CPU核心数: %ld\n", sysconf(_SC_NPROCESSORS_ONLN));
    if (bind_interface) {
        printf("绑定接口: %s\n", bind_interface);
    }
    if (multi_interface_mode) {
        printf("多接口模式: 启用\n");
    }
    printf("等待客户端连接...\n");
    printf("按Ctrl+C退出\n\n");
    
    start_time = time(NULL);
    
    while (running) {
        // 接受客户端连接
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
        
        if (client_fd == -1) {
            if (errno == EINTR) {
                continue;  // 被信号中断，继续循环
            }
            perror("接受连接失败");
            continue;
        }
        
        // 检查是否超过最大连接数
        pthread_mutex_lock(&stats_mutex);
        if (active_clients >= MAX_CLIENTS) {
            printf("警告: 已达到最大连接数 %d，拒绝新连接\n", MAX_CLIENTS);
            close(client_fd);
            pthread_mutex_unlock(&stats_mutex);
            continue;
        }
        pthread_mutex_unlock(&stats_mutex);
        
        // 创建客户端信息结构
        client_info_t *client = malloc(sizeof(client_info_t));
        if (!client) {
            perror("内存分配失败");
            close(client_fd);
            continue;
        }
        
        client->client_fd = client_fd;
        client->client_addr = client_addr;
        client->client_id = ++client_id;
        client->client_bytes = 0;
        client->connect_time = time(NULL);
        client->cpu_core = client_id % sysconf(_SC_NPROCESSORS_ONLN);
        
        // 设置源接口信息
        if (bind_interface) {
            strcpy(client->source_interface, bind_interface);
        } else {
            strcpy(client->source_interface, "系统默认");
        }
        
        // 创建线程处理客户端
        pthread_t thread;
        if (pthread_create(&thread, NULL, handle_client, client) != 0) {
            perror("创建线程失败");
            free(client);
            close(client_fd);
            continue;
        }
        
        // 分离线程，让系统自动回收资源
        pthread_detach(thread);
    }
    
    close(server_fd);
    
    // 等待所有客户端断开连接
    printf("\n等待所有客户端断开连接...\n");
    while (active_clients > 0) {
        sleep(1);
    }
    
    // 显示最终统计
    time_t end_time = time(NULL);
    double duration = difftime(end_time, start_time);
    
    printf("\n=== 服务器最终统计 ===\n");
    printf("总接收数据: %.2f MB\n", total_bytes / (1024.0 * 1024.0));
    printf("运行时间: %.2f 秒\n", duration);
    if (duration > 0) {
        double bandwidth_mbps = (total_bytes * 8.0) / (duration * 1024 * 1024);
        printf("平均聚合带宽: %.2f Mbps\n", bandwidth_mbps);
        printf("平均速度: %.2f MB/s\n", total_bytes / (duration * 1024 * 1024));
    }
    printf("====================\n");
    
    pthread_mutex_destroy(&stats_mutex);
    printf("服务器已关闭\n");
    
    return 0;
}
